package utils

import (
	"bytes"

	"io"

	//"crypto/tls"
	"encoding/base64"

	"html/template"
	//"net"

	//"io/ioutil"
	//"os"
	//"path/filepath"

	"gopkg.in/mgo.v2/bson"

	//"encoding/base64"
	//"fmt"

	"net/smtp"
	"os"
	"path"
	"path/filepath"
	"strconv"

	"github.com/jaytaylor/html2text"
)

func unescaped(x string) interface{} { return template.HTML(x) }
func b64(x string) interface{}       { return base64.StdEncoding.EncodeToString([]byte(x)) }
func boundary() interface{}          { return bson.NewObjectId().Hex() }

func (s SMTP_XML) Mail(subject, nick, from, to, body string, attachment []ATTACHMENT) error {
	auth := smtp.PlainAuth("", s.Account, s.Password, s.Server)

	type TMPMAIL_DATA struct {
		Nick    string
		From    string
		To      string
		Subject string
		Html    string
		Text    string

		Mixed      bool
		Attachment []ATTACHMENT
	}
	var text string
	var err error
	var t *template.Template

	if text, err = html2text.FromString(body); err != nil {
		return err
	}

	context := &TMPMAIL_DATA{
		nick,
		from,
		to,
		subject,
		body,
		text,
		false,
		attachment,
	}
	for _, k := range attachment {
		if !k.Inline {
			context.Mixed = true
			break
		}
	}
	dir := filepath.Dir(os.Args[0])

	const alternative = "html\\template\\alternative.txt"
	const related = "html\\template\\related.txt"
	const mixed = "html\\template\\mixed.txt"
	const multipart = "html\\template\\multipart.txt"

	if t, err = template.ParseFiles(path.Join(dir, "html\\template\\mail.txt")); err != nil {
		return err
	}

	t = t.Funcs(template.FuncMap{"unescaped": unescaped})
	t = t.Funcs(template.FuncMap{"b64": b64})
	t = t.Funcs(template.FuncMap{"boundary": boundary})

	if t, err = template.Must(t.Clone()).ParseFiles(path.Join(dir, multipart), path.Join(dir, related), path.Join(dir, mixed), path.Join(dir, alternative)); err != nil {
		return err
	}

	var doc bytes.Buffer
	if err = t.Execute(&doc, context); err != nil {
		return err
	}
	var c *smtp.Client

	if c, err = smtp.Dial(s.Server + ":" + strconv.Itoa(s.Port)); err != nil {
		return err
	}

	defer c.Close()

	if err = c.Hello("localhost"); err != nil {
		return err
	}

	if err = c.Auth(auth); err != nil {
		return err
	}

	if err = c.Mail(s.Account); err != nil {
		return err
	}

	if err = c.Rcpt(context.To); err != nil {
		return err
	}
	var w io.WriteCloser
	if w, err = c.Data(); err != nil {
		return err
	}

	if _, err = w.Write(doc.Bytes()); err != nil {
		return err
	}

	if err = w.Close(); err != nil {
		return err
	}

	return c.Quit()
}
